#ifndef PUDGE_META_LAZY_TEST_HPP
#define PUDGE_META_LAZY_TEST_HPP

#include <pudge/meta/lazy.hpp>

namespace pudge { namespace meta {

	struct lazy_test_1_
	{
		struct function_1
		{
			template<class T> struct result { typedef typename deref<T>::type type; };
			int operator()(int & i)
			{
				return i + 1;
			}
		};
		struct function_2
		{
			template<class T> struct result { typedef T type; };
			template<class T> T & operator()(T & t)
			{
				return t += 1;
			}
		};
		void operator()() const
		{
			lazy<function_1> f1 = function_1();

			int x = f1(val(1))();
			if(x != 2) throw -1;

			lazy<function_2> f2 = function_2();

			int y = 1;
			int & z = f2(ref(y))();

			if(&y != &z) throw -1;
			if(y != 2) throw -1;
		}
	} const lazy_test_1;

	struct lazy_test_2_
	{
		struct function_1
		{
			template<class T0> struct result { typedef int type; };

			int operator()(int x)
			{
				return x + 1;
			}
		};
		struct function_2
		{
			template<class T0, class T1> struct result { typedef int type; };

			int operator()(int x, int y)
			{
				return x - y;
			}
		};
		void operator()() const
		{
			lazy<function_1> f1 = function_1();

			int x = 2;
			int y = f1(_1)(x);

			if(y != 3) throw -1;

			lazy<function_2> f2 = function_2();

			x = 5;
			y = f2(_1,val(3))(x);

			if(y != 2) throw -1;

			y = f2(val(3),_1)(x);

			if(y != -2) throw -1;
		}
	} const lazy_test_2;

	void lazy_test()
	{
		lazy_test_1();
		lazy_test_2();
	}
}}

#endif